package edu.gatech.mobile.scene;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.opencv.core.Mat;
import org.opencv.features2d.DescriptorMatcher;

import android.app.Application;
import android.os.Environment;


/**
 * Application context provides global access of image data to all of the activities.
 * @author Jing
 *
 */


public class ApplicationContext extends Application {
	
	//Separate lists for holding training data IDs based on the training patch's horizon location
	private List<Long> aboveMaskImages;
	private List<Long> onMaskImages;
	private List<Long> belowMaskImages;
	
	//Storing the color of each training data patch at its label
	private List<Integer> aboveMaskColors;
	private List<Integer> onMaskColors;
	private List<Integer> belowMaskColors;

	//Nearest neighbor matcher for each type of horizon training data
	private DescriptorMatcher aboveMatcher;
	private DescriptorMatcher onMatcher;
	private DescriptorMatcher belowMatcher;

	//Mat structure for storing the training data so the descriptor matchers are able to use them 
	private Mat aboveData;
	private Mat onData;
	private Mat belowData;
	
	//Boolean variable checking if all the training data has been loaded to avoid repeatly loading training data (TOO SLOW).
	public static boolean contextLoaded = false;
	
	
	@Override
	public void onCreate() {
		super.onCreate();		
		checkFileDir();
	}
	
	/**
	 * creates neccessary folders on sdcard first time the app is installed
	 */
	private void checkFileDir() {
		File sdCard = Environment.getExternalStorageDirectory();
		File myImages = new File(sdCard + "/"+AppConstants.IMG_FOLDER);

		if (!myImages.exists()) {
			myImages.mkdir();
		}
	}
	
	
	/**
	 * add data to training data below the horizon
	 * @param data data needs to be added 
	 */
	public synchronized void updateBelowMatcher(Mat data){
		Mat newBelowData = new Mat(data.rows(), data.cols(), data.type());
		data.copyTo(newBelowData);
		data.release();
		List<Mat> belowList = new ArrayList<Mat>();
		belowList.add(newBelowData);
		this.getBelowMatcher().add(belowList);	
		System.out.println("Below data added");
	}
	
	/**
	 * add data to training data on the horizon
	 * @param data data to be added
	 */
	public synchronized void updateOnMatcher(Mat data){
		Mat newOnData = new Mat(data.rows(), data.cols(), data.type());
		data.copyTo(newOnData);
		data.release();
		List<Mat> onList = new ArrayList<Mat>();
		onList.add(newOnData);
		this.getOnMatcher().add(onList);
		System.out.println("On data added");
	}
	
	/**
	 * add data to training data above the horizon
	 * @param data data to be added
	 */
	public synchronized void updateAboveMatcher(Mat data){
		Mat newAboveData = new Mat(data.rows(), data.cols(), data.type());
		data.copyTo(newAboveData);
		data.release();
        List<Mat> aboveList = new ArrayList<Mat>();
		aboveList.add(aboveData);
		this.getAboveMatcher().add(aboveList);
		System.out.println("Above data added");
	}
	
	
	
	
	public List<Long> getAboveMaskImages() {
		return aboveMaskImages;
	}

	public void setAboveMaskImages(List<Long> aboveMaskImages) {
		this.aboveMaskImages = aboveMaskImages;
	}

	public List<Long> getOnMaskImages() {
		return onMaskImages;
	}

	public void setOnMaskImages(List<Long> onMaskImages) {
		this.onMaskImages = onMaskImages;
	}

	public List<Long> getBelowMaskImages() {
		return belowMaskImages;
	}

	public void setBelowMaskImages(List<Long> belowMaskImages) {
		this.belowMaskImages = belowMaskImages;
	}

	public List<Integer> getAboveMaskColors() {
		return aboveMaskColors;
	}

	public void setAboveMaskColors(List<Integer> aboveMaskColors) {
		this.aboveMaskColors = aboveMaskColors;
	}

	public List<Integer> getOnMaskColors() {
		return onMaskColors;
	}

	public void setOnMaskColors(List<Integer> onMaskColors) {
		this.onMaskColors = onMaskColors;
	}

	public List<Integer> getBelowMaskColors() {
		return belowMaskColors;
	}

	public void setBelowMaskColors(List<Integer> belowMaskColors) {
		this.belowMaskColors = belowMaskColors;
	}

	public synchronized DescriptorMatcher getAboveMatcher() {
		return aboveMatcher;
	}

	public void setAboveMatcher(DescriptorMatcher aboveMatcher) {
		this.aboveMatcher = aboveMatcher;
	}

	public synchronized DescriptorMatcher getOnMatcher() {
		return onMatcher;
	}

	public void setOnMatcher(DescriptorMatcher onMatcher) {
		this.onMatcher = onMatcher;
	}

	public synchronized DescriptorMatcher getBelowMatcher() {
		return belowMatcher;
	}

	public void setBelowMatcher(DescriptorMatcher belowMatcher) {
		this.belowMatcher = belowMatcher;
	}

	public Mat getAboveData() {
		return aboveData;
	}

	public void setAboveData(Mat aboveData) {
		this.aboveData = aboveData;
	}

	public Mat getOnData() {
		return onData;
	}

	public void setOnData(Mat onData) {
		this.onData = onData;
	}

	public Mat getBelowData() {
		return belowData;
	}

	public void setBelowData(Mat belowData) {
		this.belowData = belowData;
	}
	
	

}
